package com.hxm.demo.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Objects;

@Slf4j
public class TestFileReadWrite {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        fileReadByte("G:\\test.txt", "G:\\test1.txt");
        long end1 = System.currentTimeMillis();
        log.info("===============>字节流:{}", end1 - start);
        fileReadChar("G:\\test.txt", "G:\\test2.txt");
        long end2 = System.currentTimeMillis();
        log.info("===============>字符流:{}", end2 - end1);
        fileReadNio("G:\\test.txt", "G:\\test3.txt");
        long end3 = System.currentTimeMillis();
        log.info("===============>NIO:{}", end3 - end2);
        fileReadChannel("G:\\test.txt", "G:\\test4.txt");
        long end4 = System.currentTimeMillis();
        log.info("===============>channel:{}", end4 - end3);
    }


    /**
     * 字节流
     *
     * @param inPath
     * @param outPath
     */
    private static void fileReadByte(String inPath, String outPath) {
        Assert.notNull(inPath);
        Assert.notNull(outPath);
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(inPath);
            fos = new FileOutputStream(outPath);
            byte[] bytes = new byte[1024];
            int len;
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (Objects.nonNull(fis)) {
                try {
                    fis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (Objects.nonNull(fos)) {
                try {
                    fos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * 字符流
     *
     * @param inPath
     * @param outPath
     */
    private static void fileReadChar(String inPath, String outPath) {
        Assert.notNull(inPath);
        Assert.notNull(outPath);
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader(inPath);
            fw = new FileWriter(outPath);
            char[] chars = new char[2];
            int len;
            while ((len = fr.read(chars)) != -1) {
                fw.write(chars);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (Objects.nonNull(fr)) {
                try {
                    fr.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (Objects.nonNull(fw)) {
                try {
                    fw.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * MMAP
     *
     * @param inPath
     * @param outPath
     */
    private static void fileReadNio(String inPath, String outPath) {
        try {
            RandomAccessFile irandomAccessFile = new RandomAccessFile(inPath, "r");
            RandomAccessFile orandomAccessFile = new RandomAccessFile(outPath, "rw");
            FileChannel ichannel = irandomAccessFile.getChannel();
            FileChannel ochannel = orandomAccessFile.getChannel();
            long size = ichannel.size();
            MappedByteBuffer inMap = ichannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
            MappedByteBuffer outMap = ochannel.map(FileChannel.MapMode.READ_WRITE, 0, size);
            for (int i = 0; i < size; i++) {
                byte b = inMap.get(i);
                outMap.put(i, b);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * FileChannel
     *
     * @param inPath
     * @param outPath
     */
    private static void fileReadChannel(String inPath, String outPath) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel ichannel = null;
        FileChannel ochannel = null;
        try {
            fis = new FileInputStream(inPath);
            fos = new FileOutputStream(outPath);
            //获取ByteBuffer
            ichannel = fis.getChannel();
            ochannel = fos.getChannel();
            //创建Channl
            ByteBuffer allocate = ByteBuffer.allocate(4096);
            int len = 0;
            while ((len = ichannel.read(allocate)) != -1) {
                allocate.flip();
                ochannel.write(allocate);
                allocate.clear();
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (Objects.nonNull(fis)) {
                try {
                    fis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (Objects.nonNull(fos)) {
                try {
                    fos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (Objects.nonNull(ichannel)) {
                try {
                    ichannel.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (Objects.nonNull(ochannel)) {
                try {
                    ochannel.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}
